#ifndef OSGCLASS_H
#define OSGCLASS_H


#include "common.h"


class cursorZoomManipulator : public osgGA::CameraManipulator
{
public:

    //构造函数传入节点计算包围盒
    cursorZoomManipulator(osg::Node *node)
    {
        _root = node;
        computeHomePosition();
        _eye = _homeEye;
        _direction = _homeCenter - _homeEye;
        _up = _homeUp;
    }

    ~cursorZoomManipulator(){}

    //所有漫游器都必须实现的4个纯虚函数
    virtual void setByMatrix(const osg::Matrixd& matrix){}
    virtual void setByInverseMatrix(const osg::Matrixd& matrix){}
    virtual osg::Matrixd getMatrix() const{return osg::Matrix();}
    osg::Matrixd getInverseMatrix() const
    {
        osg::Matrix mat;
        mat.makeLookAt(_eye, _eye + _direction, _up);
        return mat;
    }

    //获取传入节点，用于使用CameraManipulator中的computeHomePosition
    const osg::Node* getNode() const { return _root; }
    osg::Node* getNode() { return _root;  }

    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
    {
        if(ea.getEventType() == osgGA::GUIEventAdapter::SCROLL)
        {
            osgViewer::Viewer *viewer = static_cast<osgViewer::Viewer*>(&aa);
            if(!viewer)
            {
                qDebug()<<"viewer = null";
                return false;
            }
            const osg::Camera* camera = viewer->getCamera();
            if(!camera)
            {
                qDebug()<<"camera = null";
                return false;
            }


            osg::Vec3 pt(ea.getX(),ea.getY(),0.0);
            osg::Vec3 mouseWorld = screen2World(pt,camera);
            osg::Vec3 direction = mouseWorld - _eye;
            direction.normalize();

            switch (ea.getScrollingMotion())
            {
            case osgGA::GUIEventAdapter::SCROLL_UP:
            {
                _eye += direction * 1.1;
            }
            break;
            case osgGA::GUIEventAdapter::SCROLL_DOWN:
            {
                _eye -= direction * 1.1;
            }
            break;
            default:
                break;
            }

        }
        return false;

    }
    osg::Vec3 screen2World(osg::Vec3 screenPoint,const osg::Camera* camera)
    {
        osg::Vec3d world;
        osg::Matrix mVPW = camera->getViewMatrix() * camera->getProjectionMatrix() *
                camera->getViewport()->computeWindowMatrix();
        osg::Matrix invertVPW;
        invertVPW.invert(mVPW);
        world = screenPoint * invertVPW;
        return world;

    }
    osg::Vec3 world2Screen(osg::Vec3 worldPoint,const osg::Camera* camera)
    {
        osg::Vec3d screen;
        osg::Matrix mVPW = camera->getViewMatrix() * camera->getProjectionMatrix() *
                camera->getViewport()->computeWindowMatrix();
        screen = worldPoint * mVPW;
        return screen;

    }

    osg::Vec3   _eye;               //视点位置
    osg::Vec3   _direction;         //视点方向
    osg::Vec3   _up;                //向上方向
    osg::Node*  _root;
};





class osgWidget : public QWidget, public osgViewer::CompositeViewer
{
public:
    osgWidget(): QWidget()
    {
        initViewerCamera();
        setViewerData();
        setViewerLayout();
        setTimer();
    }
    virtual void paintEvent( QPaintEvent* event )
    { frame(); }



protected:
    void initViewerCamera()
    {
        setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
        // disable the default setting of viewer.done() by pressing Escape.
        setKeyEventSetsDone(0);
        osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->windowName = "";
        traits->windowDecoration = false;
        traits->x = 0;
        traits->y = 0;
        traits->width = 800;
        traits->height = 600;
        traits->doubleBuffer = true;
        traits->alpha = ds->getMinimumNumAlphaBits();
        traits->stencil = ds->getMinimumNumStencilBits();
        traits->sampleBuffers = ds->getMultiSamples();
        traits->samples = ds->getNumMultiSamples();
        gw = new osgQt::GraphicsWindowQt(traits.get());
        view = new osgViewer::View;
        addView( view );

        osg::Camera* camera = view->getCamera();
        camera->setGraphicsContext(gw);
        camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
        camera->setProjectionMatrixAsPerspective(
            30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), -1000.0f, 10000.0f );
    }
    void setViewerLayout()
    {
        QGridLayout* grid = new QGridLayout;
        grid->addWidget( gw->getGLWidget(), 0, 0 );
        setLayout( grid );
    }
    void setTimer()
    {
        connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
        _timer.start( 10 );
    }
    virtual void setViewerData()//后面就在这里添加代码控制绘图
    {

        osg::ref_ptr<osg::Group> root = new osg::Group;
        root->addChild( createQuad());
        view->setSceneData(root);

        //按下w显示网格
        view->addEventHandler( new osgGA::StateSetManipulator(
                                   view->getCamera()->getOrCreateStateSet()) );
        view->setCameraManipulator(new cursorZoomManipulator(root));
       // view->setCameraManipulator(new osgGA::TrackballManipulator);
    }

    osg::ref_ptr<osg::Geometry> createQuad()
    {
        osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
        vertices->push_back( osg::Vec3(0.0f, 0.0f, 0.0f) );
        vertices->push_back( osg::Vec3(1.0f, 0.0f, 0.0f) );
        vertices->push_back( osg::Vec3(1.0f, 0.0f, 1.0f) );
        vertices->push_back( osg::Vec3(0.0f, 0.0f, 1.0f) );
        osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
        normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );
        osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
        colors->push_back( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
        colors->push_back( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
        colors->push_back( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
        colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
        osg::ref_ptr<osg::Geometry> quad = new osg::Geometry;
        quad->setVertexArray( vertices.get() );
        quad->setNormalArray( normals.get() );
        quad->setNormalBinding( osg::Geometry::BIND_OVERALL );
        quad->setColorArray( colors.get() );
        quad->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
        quad->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );
        return quad.release();
    }


protected:
    QTimer _timer;
    osgQt::GraphicsWindowQt* gw;
    osgViewer::View* view;
};




#endif // OSGCLASS_H
